﻿using DoNetDrive.Core.Command;
using Face8280WebSocketServer;
using Face8280WebSocketServer.Command;
using Face8280WebSocketServer.Command.Models;
using Face8280WebSocketServer.Command.Person;
using Face8280WebSocketServer.Controllers;
using Face8280WebSocketServer.DB.Access;
using Face8280WebSocketServer.DB.People;
using Face8280WebSocketServer.DTO.FacePeople;
using Face8280WebSocketServer.Interface;
using Face8280WebSocketServer.Utility;
using Face8280WebSocketServer.Utility.FilterAttribute;
using Face8280WebSocketServer.Utility.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System.Linq.Expressions;

namespace FaceFace8280WebSocketServer.Controllers.New.People
{
    [Route("api/[controller]")]
    [ApiController]
    public class PeopleNewController : ControllerBase
    {
        IFacePeopleService _FacePeopleService;
        ICacheService _CacheService;
        IFaceIOLogService _FaceIOLogService;
        public PeopleNewController(IFacePeopleService peopleService, ICacheService cacheService, IFaceIOLogService faceIOLogService)
        {
            _FacePeopleService = peopleService;
            _CacheService = cacheService;
            _FaceIOLogService = faceIOLogService;
        }
        /// <summary>
        /// 添加人员信息
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("Add")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public IActionResult Add([FromForm] Face8280WebSocketServer.DB.People.FacePeopleInfo par, [FromForm] IFormCollection files)
        {
            if (!CheckImage(files, out var data, out var result))
            {
                return new JsonResult(result);
            }
            if (data != null)
                par.PhotoData = data;
            return new JsonResult(_FacePeopleService.Add(par));
        }

        /// <summary>
        /// 添加人员信息
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("AddAndFile")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public IActionResult AddAndFile([FromForm] string postdata, [FromForm] IFormCollection files)
        {
            var oUpdatePar = JsonConvert.DeserializeObject<FacePeopleInfo>(postdata);
            IActionResult errResult = null;
            if (!VerifyActionFilterAttribute.VerifyEntity(typeof(FacePeopleInfo), oUpdatePar, r => errResult = r)) return errResult;

            return Add(oUpdatePar, files);
        }
        /// <summary>
        /// 添加人员信息
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("Update")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public IActionResult Update([FromForm] Face8280WebSocketServer.DB.People.FacePeopleInfo par, [FromForm] IFormCollection files)
        {
            if (!CheckImage(files, out var data, out var result))
            {
                return new JsonResult(result);
            }
            if (data != null)
            {
                par.PhotoData = data;
            }
            return new JsonResult(_FacePeopleService.Update(par));
        }

        /// <summary>
        /// 更新人员信息
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("UpdateAndFile")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public IActionResult UpdateAndFile([FromForm] string postdata, [FromForm] IFormCollection files)
        {
            var oUpdatePar = JsonConvert.DeserializeObject<FacePeopleInfo>(postdata);
            IActionResult errResult = null;
            if (!VerifyActionFilterAttribute.VerifyEntity(typeof(FacePeopleInfo), oUpdatePar, r => errResult = r)) return errResult;

            return Update(oUpdatePar, files);
        }

        /// <summary>
        /// 删除人员
        /// </summary>
        /// <param name="par"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("Delete")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public IActionResult Delete([FromForm] PeopleDeleteParameter par)
        {
            if (par.PeopleIDs == null)
            {
                return new JsonResult(new JsonResultModel(1, "未选择需要删除的人员"));
            }
            if (par.PeopleIDs.Count == 0)
            {
                return new JsonResult(new JsonResultModel(1, "未选择需要删除的人员"));
            }
            HashSet<int> peopleIDLists = new HashSet<int>(par.PeopleIDs);
            return new JsonResult(_FacePeopleService.Delete(peopleIDLists));
        }

        private bool CheckImage(IFormCollection files, out byte[] data, out JsonResultModel result)
        {
            result = null;
            data = null;

            if (files.Files.Count == 0) return true;

            for (int i = 0; i < files.Files.Count; i++)
            {
                var uploadFile = files.Files[i];
                if (uploadFile.Length > 0)
                {
                    if (uploadFile.Length > 20971520)//20*1024KB=20M
                    {
                        result = new JsonResultModel(202, "人员照片太大，请先压缩照片！");
                        return false;
                    }
                    string crc;
                    using var stream = new MemoryStream((int)uploadFile.Length);
                    uploadFile.CopyTo(stream);
                    byte[] bImg = stream.ToArray();
                    data = FaceImageUtil.ConvertImage(bImg);
                    //  crc = CRC32_C.CalculateDigest(bImg, 0, (uint)bImg.Length).ToString("x");

                }
            }
            return true;
        }
        [HttpGet]
        [Route("GetPeopleDetail/{id}")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public IActionResult GetPeopleDetail(int id)
        {
            return new JsonResult(new JsonResultModel(_FacePeopleService.GetPeopleById(id)));
        }

        [HttpPost]
        [Route("GetPeopleTable")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public IActionResult GetPeopleTable([FromForm] PeopleQueryParameter par)
        {

            List<Expression<Func<FacePeopleInfo, bool>>> oWheres = new();
            if (par.Code > 0) oWheres.Add(x => x.Code.Equals(par.Code));
            if (par.Card > 0) oWheres.Add(x => x.Card.Equals(par.Card));
            if (par.Photo > 0)
            {
                if (par.Photo == 1)
                    oWheres.Add(x => x.Photo != null && x.Photo.Length > 0);
                else
                    oWheres.Add(x => x.Photo == null || x.Photo.Length == 0);
            }

            if (!string.IsNullOrWhiteSpace(par.Name)) oWheres.Add(x => x.Name.Contains(par.Name));
            if (!string.IsNullOrWhiteSpace(par.Job)) oWheres.Add(x => x.Job.Contains(par.Job));
            if (!string.IsNullOrWhiteSpace(par.Phone)) oWheres.Add(x => x.Photo.Contains(par.Phone));
            //_logger.LogInformation("获取人员列表");
            var peoples = _FacePeopleService.QueryPage(
                x => new
                {
                    x.Id,
                    x.Code,
                    x.Name,
                    x.Pin,
                    x.Card,
                    x.Photo,
                    x.Job,
                    x.Phone,
                    x.Admin,
                    x.IdentityId
                },
                oWheres, par.pageSize, par.pageIndex,
                x => x.Code,
                par.isAsc);

            return new JsonResult(new JsonResultModel(peoples));


        }


        [HttpPost]
        [Route("GetPeopleTableMini")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public IActionResult GetPeopleTableMini([FromForm] PeopleQueryParameter par)
        {


            List<Expression<Func<FacePeopleInfo, bool>>> oWheres = new();
            if (par.Code > 0) oWheres.Add(x => x.Code.Equals(par.Code));
            if (par.Card > 0) oWheres.Add(x => x.Card.Equals(par.Card));
            if (par.Photo > 0)
            {
                if (par.Photo == 1)
                    oWheres.Add(x => x.Photo != null && x.Photo.Length > 0);
                else
                    oWheres.Add(x => x.Photo == null || x.Photo.Length == 0);
            }

            if (!string.IsNullOrWhiteSpace(par.Name)) oWheres.Add(x => x.Name.Contains(par.Name));
            if (!string.IsNullOrWhiteSpace(par.Job)) oWheres.Add(x => x.Job.Contains(par.Job));
            if (!string.IsNullOrWhiteSpace(par.Phone)) oWheres.Add(x => x.Photo.Contains(par.Phone));
            //_logger.LogInformation("获取人员列表");
            var peoples = _FacePeopleService.QueryPage(
                x => new
                {
                    x.Id,
                    x.Code,
                    x.Name,
                    x.Pin,
                    x.Card,
                    x.Photo
                },
                oWheres, par.pageSize, par.pageIndex,
                x => x.Code,
                par.isAsc);

            return new JsonResult(new JsonResultModel(peoples));
        }
        [HttpPost]
        [Route("RequireEnrollPerson")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public async Task<IActionResult> RequireEnrollPerson([FromForm] RequestRequireEnroll_DTO par)
        {
            try
            {
                par.EnrollType = 2;
                var first = Allocator.WebSocketClients.FirstOrDefault();
                var detail = await Allocator.GetCommandDetail(first.Value);
                detail.Timeout = 15000;
                detail.RestartCount = 0;
                RequireEnrollPerson cmd = new RequireEnrollPerson(detail, par);
                await Allocator.AddCommandAsync(cmd);
                var result = cmd.getResult() as RequireEnrollPersonResult;
                string data = null;
                if (result != null)
                {
                    if (result.JsonResultValue.FeatureData != null && result.JsonResultValue.FeatureData.BinaryData != null)
                    {
                        data = FileIOUtility.WriteFaceImage(result.JsonResultValue.Code, result.JsonResultValue.FeatureData.BinaryData);
                    }
                }
                return new JsonResult(new JsonResultModel(data));
            }
            catch (Exception ex)
            {

                return new JsonResult(new JsonResultModel("等待超时"));
            }
            
        }
        [HttpPost]
        [Route("GetDevicePeopleByCode")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public async Task<IActionResult> GetDevicePeopleByCode([FromForm] DevicePeopleQueryParameter par)
        {
            var device = _CacheService.GetDevice(par.DeviceSn);
            var comDtl = await Allocator.GetCommandDetail(device.DeviceSn);

            GetPerson cmd = new GetPerson(comDtl, par.PeopleCode);
            await Allocator.AddCommandAsync(cmd);
            var result = cmd.getResult() as GetPersonResult;
            if (result == null || result.Person.Result != 200)
            {

                return new JsonResult(new JsonResultModel(100, result.Person.Error));
            }
            var person = result.Person;
            var DevicePassStart = DateTime.Now;
            var DevicePassEnd = DateTime.Now.AddYears(1);
            if (!string.IsNullOrWhiteSpace(person.Start))
            {
                DevicePassStart = DateTime.Parse(person.Start);
            }
            if (!string.IsNullOrWhiteSpace(person.End))
            {
                DevicePassEnd= DateTime.Parse(person.End);
            }

                return new JsonResult(new JsonResultModel(new DeviceAccessDetail_DTO
            {
                DeviceID = device.DeviceSn,
                DeviceName = device.DeviceName,
                EmployeeID = person.Code,
                EmployeeName = person.Name,
                EmployeePassword = person.Pin,
                EmployeePhoto = GetPhoto(person.FeatureData),
                EmployeeIC = person.Card,
                EmployeeJob = person.Job,
                EmployeePhone = person?.Attachment?.Phone,
                EmployeeRoot = person.Admin,
                TimeGroupID = person.Tp,
                DevicePassStart = DevicePassStart,
                DevicePassEnd = DevicePassEnd,
                DevicePassTimeOver = 1,
                DevicePassNumber = person.Times
            }));
        }
        private string GetAttachment(Dictionary<string, string> Attachment, string key)
        {
            if (Attachment == null || !Attachment.ContainsKey(key))
            {
                return string.Empty;
            }
            return Attachment[key];
        }
        private string GetPhoto(List<FeatureDataModel> featureData)
        {
            if (featureData == null || featureData.Count == 0)
                return string.Empty;
            if (featureData[0].BinaryData == null) return string.Empty;
            var photoData = Convert.ToBase64String(featureData[0].BinaryData);
            return photoData;
        }
        [HttpPost]
        [Route("GetDevicePeopleAll/{DeviceSn}")]
        [TypeFilter(typeof(VerifyActionFilterAttribute))]
        public async Task<IActionResult> GetDevicePeopleAll(string DeviceSn)
        {
            var device = _CacheService.GetDevice(DeviceSn);
            var comDtl = await Allocator.GetCommandDetail(device.DeviceSn);
            List<GetPersonListModel> peoples = new List<GetPersonListModel>();
            var result = await GetPersonListModel(peoples, comDtl, 1);
            if (result.ResultObj.Result == 200)
            {
                PageResult<GetPersonListModel> pageResult = new()
                {
                    DataList = peoples,
                    PageIndex = 1,
                    PageSize = peoples.Count,
                    TotalCount = peoples.Count
                };
                return new JsonResult(new JsonResultModel(pageResult));
            }
            return new JsonResult(new JsonResultModel(100, result.ResultObj.Error));
        }

        private async Task<GetPersonListResult> GetPersonListModel(List<GetPersonListModel> peoples, INCommandDetail detail, int pageIndex)
        {
            GetPersonList cmd = new GetPersonList(detail, pageIndex,1);
            await Allocator.AddCommandAsync(cmd);
            var result = cmd.getResult() as GetPersonListResult;
            if (result.ResultObj.Result == 200)
            {
                peoples.AddRange(result.ResultObj.Persons);
                if (result.ResultObj.Total > peoples.Count)
                {
                    pageIndex++;
                    return await GetPersonListModel(peoples, detail, pageIndex);
                }
            }
            return result;
        }
    }
}
